package edu.bu.cs673.superkids123;

import javax.swing.JComponent;

import edu.bu.cs673.superkids123.common.controller.AuthenticationController;

/**
 * This class represents a view that will be shown in a JFrame for the running application
 * 
 * @author bhepburn
 *
 * @param <C>  The component which this view extends.  Usually a JPanel
 */
public abstract class AbstractView<C extends JComponent> {
	private final AbstractFrame mainFrame;

	protected AuthenticationController authController;

	/**
	 * @param mainFrame The frame this view is being added to
	 */
	public AbstractView(AbstractFrame mainFrame) {
		this.mainFrame = mainFrame;

		// All views will need to know who the user is
		authController = getMainFrame().getController(
				AuthenticationController.class);
	}

	/**
	 * This method needs to be overridden by all subclasses so the
	 * frame can get the component to be rendered
	 * 
	 * @return The component which this view builds
	 */
	protected abstract C layout();

	/**
	 * This method returns the frame this view belongs to.
	 * 
	 * @return The frame this view belongs to
	 */
	protected AbstractFrame getMainFrame() {
		return mainFrame;
	}

	/**
	 * This method is called whenever a view is being changed to by the main frame.
	 * It allows the view to determine if it should be shown.  It should return
	 * the abstract view that should be shown, which is usually itself.  By 
	 * overriding this method each view can perform additional checks.
	 * 
	 * @return The view that should be rendered in the main frame
	 */
	protected AbstractView<? extends JComponent> initializeView() {
		return this;
	}
	
	/**
	 * This method is called whenever a view is being changed to by the main frame.
	 * It allows for the view to do cleanup.  If the cleanup fails the view can return
	 * false and the view will not be changed.  By overriding this method each view
	 * can perform its own cleanup and determine if it can be changed.  Views should
	 * also be able to handle multiple cleanups.
	 * 
	 * @return True if the frame can proceed with change
	 */
	protected boolean cleanupView() {
		return true;
	}

	/**
	 * This method is called by main frame when trying to render a view.
	 * 
	 * @return The component to be rendered
	 */
	protected C getContentPane() {
		return layout();
	}
}
